import time
import random
import json
import os
from datetime import datetime
from typing import Dict

class SignInPlugin(JCbotPlugin):
    """签到插件 - 支持每日签到、积分系统和排行榜功能"""
    
    def __init__(self, bot_instance):
        super().__init__(bot_instance)
        self.plugin_name = "签到插件"
        self.version = "1.0.0"
        self.description = "签到插件，支持每日签到、积分系统和排行榜功能"
        
        # 插件内部状态
        self.command_count = 0
        self.last_command_time = 0
        self.user_stats = {}  # 用户使用统计
        
        # 插件配置（使用中文键名）
        self.config = {
            "基础积分": 10,      # 基础积分
            "连续签到奖励": 5,  # 连续签到奖励
            "最大连续天数": 7,    # 最大连续签到天数
            "随机奖励最小值": 1,   # 随机奖励最小值
            "随机奖励最大值": 10,  # 随机奖励最大值
            "命令冷却时间": 10, # 命令冷却时间
            "每日最大命令次数": 50  # 每日最大命令次数
        }
        
        # 用户数据
        self.user_data = {}
        
        # 加载配置和数据
        self.load_config()
        
    def get_handlers(self):
        """返回插件提供的所有命令处理器"""
        return {
            "sign_in": self.handle_sign_in,
            "check_points": self.handle_check_points,
            "points_rank": self.handle_points_rank,
            "sign_in_config": self.handle_config
        }
        
    def get_commands_config(self):
        """返回插件要注册的命令配置"""
        return {
            "签到": {
                "description": "每日签到获取积分",
                "handler": "sign_in",
                "permission": 1,
                "fuzzy_match": False,
                "group": "签到插件"
            },
            "我的积分": {
                "description": "查看自己的积分和签到状态",
                "handler": "check_points",
                "permission": 1,
                "fuzzy_match": False,
                "group": "签到插件"
            },
            "积分榜": {
                "description": "查看积分排行榜",
                "handler": "points_rank",
                "permission": 1,
                "fuzzy_match": False,
                "group": "签到插件"
            },
            "签到设置": {
                "description": "查看或修改签到配置（管理员专用）",
                "handler": "sign_in_config",
                "permission": 2,  # 需要管理员权限
                "fuzzy_match": False,
                "group": "签到插件"
            }
        }
        
    def register(self):
        """插件注册时调用"""
        self.bot.logger.info(f"✅ 签到插件 v{self.version} 注册成功！")
        self.bot.logger.info(f"📝 插件描述: {self.description}")
        
    def get_config_path(self):
        """获取插件配置文件路径（放在插件自己的目录下）"""
        # 获取当前插件文件的路径
        plugin_file_path = os.path.abspath(__file__)
        plugin_dir = os.path.dirname(plugin_file_path)
        
        # 返回配置文件路径
        return os.path.join(plugin_dir, "config.json")
        
    def load_config(self):
        """加载插件配置和数据"""
        try:
            config_path = self.get_config_path()
            if os.path.exists(config_path):
                with open(config_path, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                    
                    # 加载配置
                    if "config" in data:
                        self.config.update(data["config"])
                    
                    # 加载用户数据
                    if "user_data" in data:
                        self.user_data = data["user_data"]
                    
                    # 加载统计信息
                    if "stats" in data:
                        self.command_count = data["stats"].get("command_count", 0)
                        self.user_stats = data["stats"].get("user_stats", {})
                        
                self.bot.logger.info("✅ 签到插件配置加载成功")
        except Exception as e:
            self.bot.logger.error(f"❌ 加载签到插件配置失败: {e}")
            
    def save_config(self):
        """保存插件配置和数据"""
        try:
            config_path = self.get_config_path()
            
            data = {
                "config": self.config,
                "user_data": self.user_data,
                "stats": {
                    "command_count": self.command_count,
                    "user_stats": self.user_stats
                }
            }
            
            with open(config_path, 'w', encoding='utf-8') as f:
                json.dump(data, f, indent=4, ensure_ascii=False)
            self.bot.logger.info("✅ 签到插件配置保存成功")
        except Exception as e:
            self.bot.logger.error(f"❌ 保存签到插件配置失败: {e}")
            
    def update_user_stats(self, user_id: int):
        """更新用户统计"""
        today = datetime.now().strftime("%Y-%m-%d")
        if user_id not in self.user_stats:
            self.user_stats[user_id] = {}
        if today not in self.user_stats[user_id]:
            self.user_stats[user_id][today] = 0
        self.user_stats[user_id][today] += 1
        
    def check_cooldown(self, user_id: int) -> bool:
        """检查命令冷却时间"""
        current_time = time.time()
        if current_time - self.last_command_time < self.config["命令冷却时间"]:
            return False
        self.last_command_time = current_time
        return True
        
    def check_daily_limit(self, user_id: int) -> bool:
        """检查每日使用限制"""
        today = datetime.now().strftime("%Y-%m-%d")
        user_daily_count = self.user_stats.get(user_id, {}).get(today, 0)
        return user_daily_count < self.config["每日最大命令次数"]
    
    def get_user_data(self, user_id: int) -> Dict:
        """获取用户数据，如果不存在则初始化"""
        if user_id not in self.user_data:
            self.user_data[user_id] = {
                "points": 0,
                "continuous_days": 0,
                "last_sign_date": None,
                "total_days": 0
            }
        return self.user_data[user_id]
    
    def is_same_day(self, date1: str, date2: str) -> bool:
        """判断两个日期字符串是否是同一天"""
        if not date1 or not date2:
            return False
        
        try:
            d1 = datetime.strptime(date1, "%Y-%m-%d")
            d2 = datetime.strptime(date2, "%Y-%m-%d")
            return d1.date() == d2.date()
        except:
            return False
    
    def is_consecutive_day(self, last_date: str, current_date: str) -> bool:
        """判断两个日期是否是连续的"""
        if not last_date or not current_date:
            return False
        
        try:
            last_d = datetime.strptime(last_date, "%Y-%m-%d")
            current_d = datetime.strptime(current_date, "%Y-%m-%d")
            return (current_d - last_d).days == 1
        except:
            return False
    
    def get_today_date(self) -> str:
        """获取今天的日期字符串"""
        return datetime.now().strftime("%Y-%m-%d")
    
    def calculate_reward(self, user_data: Dict) -> Dict:
        """计算签到奖励"""
        today = self.get_today_date()
        last_date = user_data.get("last_sign_date")
        
        # 判断是否是连续签到
        if last_date and self.is_consecutive_day(last_date, today):
            user_data["continuous_days"] = min(
                user_data.get("continuous_days", 0) + 1,
                self.config["最大连续天数"]
            )
        elif last_date and not self.is_same_day(last_date, today):
            # 如果不是连续签到，重置连续天数
            user_data["continuous_days"] = 1
        
        # 计算基础奖励
        base_points = self.config["基础积分"]
        
        # 计算连续签到奖励
        continuous_bonus = self.config["连续签到奖励"] * user_data["continuous_days"]
        
        # 计算随机奖励
        random_bonus = random.randint(
            self.config["随机奖励最小值"],
            self.config["随机奖励最大值"]
        )
        
        # 总奖励
        total_points = base_points + continuous_bonus + random_bonus
        
        return {
            "base": base_points,
            "continuous": continuous_bonus,
            "random": random_bonus,
            "total": total_points
        }
    
    # ========== 命令处理器 ==========
    
    async def handle_sign_in(self, group_id: int, user_id: int, command: str, param: str, options: Dict = None) -> str:
        """处理签到命令"""
        self.command_count += 1
        self.update_user_stats(user_id)
        
        # 检查冷却时间
        if not self.check_cooldown(user_id):
            return "命令冷却中，请稍后再试！"
            
        # 检查每日限制
        if not self.check_daily_limit(user_id):
            return f"今日命令次数已达上限 ({self.config['每日最大命令次数']}次)"
        
        # 获取用户数据
        user_data = self.get_user_data(user_id)
        today = self.get_today_date()
        
        # 检查今天是否已经签到
        if user_data.get("last_sign_date") and self.is_same_day(user_data["last_sign_date"], today):
            return "你今天已经签到过了，请明天再来吧！"
        
        # 计算奖励
        reward = self.calculate_reward(user_data)
        
        # 更新用户数据
        user_data["points"] += reward["total"]
        user_data["last_sign_date"] = today
        user_data["total_days"] += 1
        
        # 保存数据
        self.save_config()
        
        # 获取用户名
        user_name = await self.get_user_name(group_id, user_id)
        
        # 构建响应消息
        response = f"✅ {user_name} 签到成功！\n"
        response += f"• 获得积分: {reward['total']}点\n"
        response += f"  - 基础奖励: {reward['base']}点\n"
        response += f"  - 连续签到: {user_data['continuous_days']}天 (+{reward['continuous']}点)\n"
        response += f"  - 随机奖励: +{reward['random']}点\n"
        response += f"• 总积分: {user_data['points']}点\n"
        response += f"• 总签到: {user_data['total_days']}天"
        
        return response
        
    async def handle_check_points(self, group_id: int, user_id: int, command: str, param: str, options: Dict = None) -> str:
        """处理查看积分命令"""
        self.command_count += 1
        self.update_user_stats(user_id)
        
        # 获取用户数据
        user_data = self.get_user_data(user_id)
        today = self.get_today_date()
        
        # 检查今天是否已经签到
        signed_today = user_data.get("last_sign_date") and self.is_same_day(user_data["last_sign_date"], today)
        
        # 获取用户名
        user_name = await self.get_user_name(group_id, user_id)
        
        # 构建响应消息
        response = f"📊 {user_name} 的积分信息:\n"
        response += f"• 总积分: {user_data['points']}点\n"
        response += f"• 连续签到: {user_data['continuous_days']}天\n"
        response += f"• 总签到: {user_data['total_days']}天\n"
        response += f"• 今日签到: {'✅ 已签到' if signed_today else '❌ 未签到'}"
        
        return response
        
    async def handle_points_rank(self, group_id: int, user_id: int, command: str, param: str, options: Dict = None) -> str:
        """处理积分排行榜命令"""
        self.command_count += 1
        self.update_user_stats(user_id)
        
        # 获取前10名用户
        sorted_users = sorted(
            self.user_data.items(),
            key=lambda x: x[1].get("points", 0),
            reverse=True
        )[:10]
        
        if not sorted_users:
            return "暂无积分数据，快来签到吧！"
        
        # 构建排行榜消息
        response = "🏆 积分排行榜 TOP10:\n"
        for i, (uid, data) in enumerate(sorted_users, 1):
            # 获取用户名
            user_name = await self.get_user_name(group_id, uid)
            points = data.get("points", 0)
            
            # 添加奖杯表情
            if i == 1:
                rank_icon = "🥇"
            elif i == 2:
                rank_icon = "🥈"
            elif i == 3:
                rank_icon = "🥉"
            else:
                rank_icon = f"{i}."
            
            response += f"{rank_icon} {user_name}: {points}分\n"
        
        # 添加当前用户排名（如果不在前10）
        current_user_data = self.get_user_data(user_id)
        current_points = current_user_data.get("points", 0)
        
        # 计算总排名
        all_users = sorted(
            self.user_data.items(),
            key=lambda x: x[1].get("points", 0),
            reverse=True
        )
        
        user_rank = None
        for i, (uid, _) in enumerate(all_users, 1):
            if uid == user_id:
                user_rank = i
                break
        
        if user_rank and user_rank > 10:
            response += f"\n你的排名: 第{user_rank}名 (积分: {current_points})"
        
        return response
        
    async def handle_config(self, group_id: int, user_id: int, command: str, param: str, options: Dict = None) -> str:
        """处理配置命令"""
        self.command_count += 1
        
        # 检查用户权限
        user_permission = self.bot.get_user_permission(user_id)
        if user_permission < 2:  # 需要管理员权限
            return "❌ 权限不足，需要管理员权限"
            
        if not param:
            # 显示当前配置
            config_info = "⚙️ 签到插件当前配置：\n"
            for key, value in self.config.items():
                config_info += f"• {key}: {value}\n"
            config_info += "\n使用：签到设置 [配置项] [值] 来修改配置"
            return config_info
            
        # 解析参数
        parts = param.split()
        if len(parts) == 1:
            # 查看特定配置项
            key = parts[0]
            if key in self.config:
                return f"🔧 {key} = {self.config[key]}"
            else:
                return f"❌ 未知配置项: {key}"
                
        elif len(parts) >= 2:
            # 修改配置
            key = parts[0]
            new_value = parts[1]
            
            if key not in self.config:
                return f"❌ 未知配置项: {key}"
                
            # 类型转换
            old_value = self.config[key]
            try:
                if isinstance(old_value, bool):
                    if new_value.lower() in ['true', '1', 'yes', 'on']:
                        new_value = True
                    elif new_value.lower() in ['false', '0', 'no', 'off']:
                        new_value = False
                    else:
                        return f"❌ 布尔值应为 true/false"
                elif isinstance(old_value, int):
                    new_value = int(new_value)
                elif isinstance(old_value, float):
                    new_value = float(new_value)
                # 字符串不需要转换
                    
                self.config[key] = new_value
                self.save_config()
                return f"✅ 配置已更新：{key} = {old_value} → {new_value}"
            except ValueError:
                return f"❌ 值类型不匹配，期望类型: {type(old_value).__name__}"
                
        return "❌ 参数格式错误"
            
    # ========== 辅助方法 ==========
    
    async def get_user_name(self, group_id: int, user_id: int) -> str:
        """获取用户名（使用主程序的API）"""
        try:
            # 调用主程序的API获取用户信息
            result = await self.bot.call_api("get_group_member_info", {
                "group_id": group_id,
                "user_id": user_id
            })
            
            if result and "data" in result:
                member_info = result["data"]
                return member_info.get("card") or member_info.get("nickname", f"用户{user_id}")
        except Exception as e:
            self.bot.logger.error(f"获取用户信息失败: {e}")
        
        return f"用户{user_id}"